package com.pactera.asmp.server.common.lock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisLock implements Lock {
    private static final String REDIS_KEY_WS_LOCK = "LOCK_WS";
    private static final long REDIS_KEY_WS_LOCK_EXPIRE_SECOND= 10l;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    @Qualifier("unLockScript")
    private DefaultRedisScript unLockScript;

    @Override
    public void lock(String uuid) {
        if(uuid.indexOf('@') != -1) uuid = uuid.split("@")[0];
        // 1、尝试加锁
        if(tryLock(uuid)) {
            return;
        }
        // 2.休眠
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 3.递归再次调用
        lock(uuid);
    }

    @Override
    public void unlock(String uuid) {
        List<String> hashKey = new ArrayList<>();
        hashKey.add(REDIS_KEY_WS_LOCK);
        hashKey.add(uuid);
        stringRedisTemplate.execute(unLockScript, hashKey);
    }

    /**
     * 	非阻塞式加锁，成功，就成功，失败就失败。直接返回
     */
    private boolean tryLock(String uuid) {
        return stringRedisTemplate.opsForValue().setIfAbsent(REDIS_KEY_WS_LOCK, uuid, REDIS_KEY_WS_LOCK_EXPIRE_SECOND, TimeUnit.SECONDS);
    }
}
